#include "./BSP/MPU6050/MPU6050_I2C.h"

void MPU6050_IO_init(void)
{
	GPIO_InitTypeDef gpio_init_struct;

	__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟

	gpio_init_struct.Pin = GPIO_PIN_10 | GPIO_PIN_11; //PB10 PB11
	gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出
	gpio_init_struct.Pull = GPIO_NOPULL; //不拉
	gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; //高速

	HAL_GPIO_Init(GPIOB, &gpio_init_struct); //初始化GPIOB的10和11引脚

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_SET); //设置PB10和PB11为高电平
}

//I2C写SCL引脚
void MPU6050_W_SCL(uint8_t Bitvalue)
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, (GPIO_PinState)(Bitvalue));
	delay_us(10);
}
//I2C写SDA引脚
void MPU6050_W_SDA(uint8_t Bitvalue)
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, (GPIO_PinState)(Bitvalue));
	delay_us(10);
}
//I2C读SDA引脚
uint8_t MPU6050_R_SDA(void)
{
	uint8_t Bitvalue;
	Bitvalue = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11);
	delay_us(10);
	return Bitvalue;
}

//产生MPU6050_IIC起始信号
void MPU6050_IIC_Start(void)
{
	MPU6050_W_SDA(1); //确保SDA为高电平
	MPU6050_W_SCL(1); //确保SCL为高电平
	MPU6050_W_SDA(0); //在SCL高电平期间，拉低SDA，产生起始信号
	MPU6050_W_SCL(0); //起始后把SCL也拉低，即为了占用总线，也为了方便总线时序的拼接
}	  

//产生MPU6050_IIC停止信号
void MPU6050_IIC_Stop(void)
{
	MPU6050_W_SDA(0); //确保SDA为低电平
	MPU6050_W_SCL(1); //确保SCL为高电平
	MPU6050_W_SDA(1); //在SCL高电平期间，拉高SDA，产生停止信号			   	
}

//接收一个字节
uint8_t MPU6050_Receive(void)
{
	uint8_t i=0x00;
	uint8_t ReceiveData = 0x00;
	MPU6050_W_SDA(1); //释放SDA线，准备接收数据
	for ( i = 0; i < 8; i++)
	{	
		MPU6050_W_SCL(1);
		if (MPU6050_R_SDA()) //读取SDA线的状态
		{
			ReceiveData |= (0x80>>i); //将读取到的SDA线状态存入ReceiveData
		}
		MPU6050_W_SCL(0);
	}
	return ReceiveData; //返回接收到的数据
}

//发送一个字节
void MPU6050_SendByte(uint8_t SendByte)
{
	uint8_t i = 0;
	for (i = 0; i < 8; i++)
	{
		MPU6050_W_SDA(!!(SendByte & (0x80 >> i))); //取SendByte的每一位数据并写入SDA线
		MPU6050_W_SCL(1); //释放SCL线，准备发送数据
		MPU6050_W_SCL(0); //拉低SCL线，完成数据发送
	}
}

//发送应答位
void MPU6050_SendAck(uint8_t AckBit)
{
	MPU6050_W_SDA(AckBit); //写应答位
	MPU6050_W_SCL(1); //释放SCL线，准备发送应答位
	MPU6050_W_SCL(0); //拉低SCL线，完成应答位发送
}

//接收应答位
uint8_t MPU6050_ReceiveAck(void)
{
	uint8_t AckBit;
	MPU6050_W_SDA(1); //释放SDA线，准备接收应答位
	MPU6050_W_SCL(1); //释放SCL线，准备接收应答位
	AckBit = MPU6050_R_SDA(); //读取SDA线的状态
	MPU6050_W_SCL(0); //拉低SCL线，完成应答位接收
	return AckBit; //返回应答位
}
